﻿using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Threading;
using System.IO.IsolatedStorage;
using Windows.Devices.Geolocation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Maps.Controls;
using Microsoft.Phone.Maps.Toolkit;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Net.NetworkInformation;
using Microsoft.Phone.Maps.Services;
using Microsoft.Phone.Tasks;
using Coding4Fun.Phone.Controls;
using RadarGlobal.Resources;
using RadarGlobal.MapClass;
using RadarGlobal.UIView;

namespace RadarGlobal
{
    public partial class MainPage : PhoneApplicationPage
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

        ApplicationBarController barControl;
      
        MapDraw mapdraw;

        CustomPushpin pushpin = new CustomPushpin();

        List<CustomPushpin> lsFind = new List<CustomPushpin>();

        CustomPushpin findPushpin = new CustomPushpin();

        double RadarZoom=1000;

        GeoCoordinate center;

        MapRoute mappedRoute = null;

        Thread ThreadScan;

        MapViewMember viewMember = new MapViewMember();

        Status status = new Status();

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            InitializeMapControl();

            InitializeGPS();

            InitializeDrawMap();

            InitiaizeControl();
        }
        #region Khởi tạo thông tin
        private void InitializeMapControl()
        {
            MapControl.Center = new GeoCoordinate(16.4575, 107.5840);

            MapControl.SetView(MapControl.Center, 15);

            mapdraw = new MapDraw(MapControl);

            findPushpin.SetImagePushpin(MapControl);
        }

        private void InitializeGPS()
        {
            if (App.Geolocator == null)
            {
                App.Geolocator = new Geolocator();
                App.Geolocator.DesiredAccuracy = PositionAccuracy.High;
                App.Geolocator.MovementThreshold = 100; // 100 meters
                App.Geolocator.StatusChanged += geolocator_StatusChanged;
                App.Geolocator.PositionChanged += geolocator_PositionChanged;
            }
        }

        private void InitializeDrawMap()
        {
            ThreadScan = new Thread((ThreadStart)delegate()
            {
                double UpdateLocationTracking = 0.0;

                while (true)
                {
                    Thread.Sleep(100);

                    UpdateLocationTracking += 100;

                    Dispatcher.BeginInvoke(() =>
                    {
                        if (center != null)
                        {
                            mapdraw.TransForms(center, RadarZoom);

                            pushpin.UpdateLocation(center);
                        }

                        if (UpdateLocationTracking >= 10000)
                        {
                            Dispatcher.BeginInvoke(() => viewMember.LoadAllGroupUser(MapControl, mapdraw.getRadar(), Global.UserInfo.UserID));

                            UpdateLocationTracking = 0;
                        }
                    });

                }
            });
            ThreadScan.Start();
        }

        private void InitiaizeControl()
        {
            barControl = new ApplicationBarController(this.ApplicationBar);

            barControl.AddNewButton("me", "/icons/Location.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton("find", "/icons/appbar.feature.search.rest.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton("directions", "/icons/Route.png", true, ApplicationBarButton_Click);

            barControl.AddNewButton("refresh", "/icons/appbar.refresh.rest.png", true, ApplicationBarButton_Click);

            barControl.AddNewMenuItem("delete directions", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("login", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("group", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("logout", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("application settings", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("rate application", true, ApplicationBarMenu_Click);

            barControl.AddNewMenuItem("about", true, ApplicationBarMenu_Click);

            barControl.ShowButtons("directions", "me", "find", "refresh");

            barControl.ShowMenuItems("login", "delete directions", "application settings", "rate application", "about");
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            StopLocationTracking();

            InitializeGPS();

            if (settings == null) return;

            if (settings.Contains("Login"))
            {
                if ((bool)settings["Login"] == true)
                {
                    barControl.RemoveMenuItems("login", "delete directions", "application settings", "rate application", "about");
                    barControl.ShowMenuItems("group", "logout", "delete directions", "application settings", "rate application", "about");
                    if (NetworkInterface.GetIsNetworkAvailable() == true && mapdraw!=null)
                    {
                        viewMember.LoadAllGroupUser(MapControl, mapdraw.getRadar(), Global.UserInfo.UserID);
                    };
                }
               else
               {
                   barControl.RemoveMenuItems("group", "logout", "delete directions", "application settings", "rate application", "about");
                   barControl.ShowMenuItems("login", "delete directions", "application settings", "rate application", "about");
                }
            }

            if (settings.Contains("MapView"))
            {
                if ((bool)settings["MapView"] == true)
                {
                    MapControl.CartographicMode = Microsoft.Phone.Maps.Controls.MapCartographicMode.Aerial;
                }
                else
                {
                    MapControl.CartographicMode = Microsoft.Phone.Maps.Controls.MapCartographicMode.Road;
                }
            }

            if (settings.Contains("RadarZoom"))
            {
                double Zoomvalue;

                if (double.TryParse(settings["RadarZoom"].ToString(), out Zoomvalue))
                {
                    RadarZoom = Zoomvalue;

                    if(center!=null)

                        mapdraw.UpdateRadarLocation(center, RadarZoom);
                }
                else
                    Zoomvalue = 1000;
            }
            else
                settings.Add("RadarZoom", this.RadarZoom);

            if(center!=null)
                MapControl.SetView(center, 15);

            base.OnNavigatedTo(e);
        }
        #endregion

        #region Event for Control

        private void ApplicationBarButton_Click(object sender, EventArgs e)
        {
            ApplicationBarIconButton btn = (ApplicationBarIconButton)sender;

            string text = btn.Text.ToLower();

            if (text == "me")
            {
                MapControl.SetView(center,15);
            }
            if (text == "refresh")
            {
                MapControl.SetView(center, 15);

                foreach (CustomPushpin find in lsFind)
                {
                    find.RemovePushpin(MapControl);
                }
                lsFind.Clear();

                if (mappedRoute != null)
                {
                    MapControl.RemoveRoute(mappedRoute);

                    mappedRoute = null;
                }

                if (NetworkInterface.GetIsNetworkAvailable() == true && mapdraw != null)
                {
                    viewMember.LoadAllGroupUser(MapControl, mapdraw.getRadar(), Global.UserInfo.UserID);
                };
            }

            if (text == "find")
            {
                InputPrompt input = new InputPrompt();
                input.Completed += (s, args) =>
                {
                    SearchLocationAdress(args.Result);
                };
                input.Title = "Find address location";
                input.Message = "Input address name you want find :";
                input.Show();
            }

            if (text == "directions")
            {
                InputPrompt input = new InputPrompt();
                input.Completed += (s, args) =>
                {
                    RouteMetoLocation(args.Result);
                };
                input.Title = "Direction location";
                input.Message = "Input address name you want directions :";
                input.Show();
            }
        }

        private void ApplicationBarMenu_Click(object sender, EventArgs e)
        {
            ApplicationBarMenuItem btn = (ApplicationBarMenuItem)sender;

            string text = btn.Text.ToLower();
            if (text == "group")
            {
                NavigationService.Navigate(new Uri("/UIView/GroupDlg.xaml", UriKind.RelativeOrAbsolute));
            }

            if (text == "logout")
            {
                barControl.RemoveMenuItems("group", "logout", "application settings", "rate application", "about");

                barControl.ShowMenuItems("login", "delete directions", "application settings", "rate application", "about");

                    if (settings.Contains("Login"))
                    {
                        settings["Login"] = false;
                    }
                    Global.DeleteSettings();
            }

            if (text == "login")
            {
                NavigationService.Navigate(new Uri("/UIView/LoginDlg.xaml",UriKind.RelativeOrAbsolute));
            }

            if(text=="application settings")
            {
                NavigationService.Navigate(new Uri("/UIView/SettingDlg.xaml", UriKind.RelativeOrAbsolute));
            }

            if (text == "delete directions")
            {
                foreach (CustomPushpin find in lsFind)
                {
                    find.RemovePushpin(MapControl);
                }
                lsFind.Clear();

                if (mappedRoute != null)
                {
                    MapControl.RemoveRoute(mappedRoute);

                    mappedRoute = null;
                }
            }
            if (text == "rate application")
            {
                RateMyApp.WP.Core.RateMyAppControl control = new RateMyApp.WP.Core.RateMyAppControl();

                control.Start(false, new RateMyApp.Core.Rate.RateControlLanguagePack()
                {
                    RateMyAppCancelText = "No thanks",
                    RateMyAppFeedbackEmail = "final_fantasy1121@yahoo.com",
                    RateMyAppHeader = "Enjoying rate Global Radar",
                    RateMyAppText = "We'd love you to rate our app 5 stars",
                    RateMyAppThridOptionText = "Send feedback by e-mail",
                    RateMyAppYesText = "Rate 5 stars"
                }, null, new int[] { 1, 2, 3, 4, 5, 6 });
            }
            if (text == "about")
            {
                // Tạo Popup hiện thị thông tin cá nhân tác giả
                AboutPrompt about = new AboutPrompt();
                about.Title = "Global Radar";
                about.Footer = "Copyright Mirufa 2014";
                about.VersionNumber = "Version 1.1.0.0";
                //about.WaterMark = "Popup menu About";
                about.Body = new TextBlock { Text = "\n\nAuthor: Nguyễn Ngọc Lân\nNickname: Mirufa1121 \nSkype: mirufa1121 \nLocation:Vietname\nPhone:01215.733.711\nThanks you for using application\nWebiste: wait update...\n", TextWrapping = TextWrapping.Wrap };
                about.Show();
            }
        }

        private async void SearchLocationAdress(string Address)
        {
            if (NetworkInterface.GetIsNetworkAvailable() != true) return;

            if (Address==null ||Address == "") return;

            status.ShowPopup("Wait searching location...!");

            var myPosition = await new Geolocator().GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10));

            var geoQuery = new GeocodeQuery();
            geoQuery.SearchTerm = Address;
            geoQuery.GeoCoordinate = new GeoCoordinate(myPosition.Coordinate.Latitude, myPosition.Coordinate.Longitude);
            geoQuery.QueryCompleted += (s, e) =>
            {
                if (e.Error == null && e.Result.Count > 0)
                {
                    foreach(CustomPushpin find in lsFind)
                    {
                        find.RemovePushpin(MapControl);
                    }
                    lsFind.Clear();

                    if (mappedRoute != null)
                    {
                        MapControl.RemoveRoute(mappedRoute);

                        mappedRoute = null;
                    }

                    foreach(MapLocation result in e.Result)
                    {
                        CustomPushpin item=new CustomPushpin();
                        item.SetImagePushpin(MapControl);
                        item.UpdateLocation(result.GeoCoordinate);
                        lsFind.Add(item);
                        MapControl.Center = result.GeoCoordinate;
                    }
                    status.Remove();
                }
            };
            geoQuery.QueryAsync();
        }

        private async void RouteMetoLocation(string Address)
        {
            if (NetworkInterface.GetIsNetworkAvailable() != true) return;

            if (Address == "") return;

            status.ShowPopup("Wait searching location...!");

            var myPosition = await new Geolocator().GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10));

            var geoQuery = new GeocodeQuery();
            geoQuery.SearchTerm = Address;
            geoQuery.GeoCoordinate = new GeoCoordinate(myPosition.Coordinate.Latitude, myPosition.Coordinate.Longitude);
            geoQuery.QueryCompleted += (s, e) =>
            {
                if (e.Error == null && e.Result.Count > 0)
                {
                    foreach (CustomPushpin find in lsFind)
                    {
                        find.RemovePushpin(MapControl);
                    }
                    lsFind.Clear();

                    List<GeoCoordinate> wayPoints = new List<GeoCoordinate>();

                    wayPoints.Add(center);

                    foreach (MapLocation result in e.Result)
                    {
                        CustomPushpin item = new CustomPushpin();
                        item.SetImagePushpin(MapControl);
                        item.UpdateLocation(result.GeoCoordinate);
                        wayPoints.Add(result.GeoCoordinate);
                        lsFind.Add(item);
                    }
                    RouteTo(wayPoints);
                }
            };
            geoQuery.QueryAsync();
        }
        private void RouteTo(List<GeoCoordinate> wayPoints)
        {
            status.ShowPopup("Wait caculator route..!");

            RouteQuery routeQuery = new RouteQuery();

            routeQuery.QueryCompleted += routeQuery_QueryCompleted;
            routeQuery.TravelMode = TravelMode.Driving;
            routeQuery.Waypoints = wayPoints;
            routeQuery.QueryAsync();


        }
        private void RouteTo(GeoCoordinate From, GeoCoordinate To)
        {

            List<GeoCoordinate> wayPoints = new List<GeoCoordinate>();
            wayPoints.Add(From);
            wayPoints.Add(To);

            RouteQuery routeQuery = new RouteQuery();

            routeQuery.QueryCompleted += routeQuery_QueryCompleted;
            routeQuery.TravelMode = TravelMode.Walking;
            routeQuery.Waypoints = wayPoints;
            routeQuery.QueryAsync();


        }
        void routeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
        {
            if (null == e.Error)
            {
                if (mappedRoute != null)
                {
                    MapControl.RemoveRoute(mappedRoute);

                    mappedRoute = null;
                }
                Route MyRoute = e.Result;
                mappedRoute = new MapRoute(MyRoute);
                MapControl.AddRoute(mappedRoute);
                MapControl.SetView(mappedRoute.Route.BoundingBox);

                status.Remove();
            }
        }
        #endregion

        #region SetZoomLevel MapControl

        private void ZoomOut_Click(object sender, RoutedEventArgs e)
        {
            if (MapControl.ZoomLevel <= 2) return;

            MapControl.ZoomLevel--;
        }

        private void ZoomIn_Click(object sender, RoutedEventArgs e)
        {
            if (MapControl.ZoomLevel >= 19) return;

            MapControl.ZoomLevel++;
        }

        void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
        {
            string positionString = this.GetCoordinateString(args.Position.Coordinate);

            if (!App.RunningInBackground)
            {
                // IMPORTANT: the event handler is called on a worker thread,
                // so we must use the Dispatcher to update the UI from the main thread
                Dispatcher.BeginInvoke(() =>
                {
                    try
                    {
                        SpeedValue.Value = (double)args.Position.Coordinate.Speed;
                        SpeedLabel.Text = SpeedValue.Value.ToString();

                        center = new GeoCoordinate()
                        {
                            Altitude = (double)args.Position.Coordinate.Altitude,
                            Latitude = args.Position.Coordinate.Latitude,
                            Longitude = args.Position.Coordinate.Longitude,
                            VerticalAccuracy = (double)args.Position.Coordinate.AltitudeAccuracy
                        };

                        mapdraw.UpdateMyLocation(center);

                        mapdraw.UpdateRadarLocation(center, RadarZoom);

                        MapControl.SetView(center, MapControl.ZoomLevel);

                        if (txtStatus.Text.IndexOf("Status : ready") >= 0 || txtStatus.Text.IndexOf("Trạng thái:") >= 0)

                            this.txtStatus.Text = string.Format("Status : ready , {0}", positionString);

                        if (settings.Contains("Login") && (bool)settings["Login"] == true)
                        {
                            mySQLService.RadarServicePortTypeClient client = new mySQLService.RadarServicePortTypeClient();

                            client.UpdateLocationAsync(Global.UserInfo.UserID, center.Latitude, center.Longitude, "No comment");
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                });
            }
            else
            {
                if (settings.Contains("Login") && (bool)settings["Login"] == true)
                {
                    mySQLService.RadarServicePortTypeClient client = new mySQLService.RadarServicePortTypeClient();

                    client.UpdateLocationAsync(Global.UserInfo.UserID, args.Position.Coordinate.Latitude, args.Position.Coordinate.Longitude, "No comment");
                }
            }
        }
        private string GetCoordinateString(Geocoordinate coordinate)
        {
            string positionString = string.Format("Lat: {0:0.0000}, Long: {1:0.0000}, Acc: {2}m",
                        coordinate.Latitude, coordinate.Longitude, coordinate.Accuracy);
            return positionString;
        }
        private void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
        {
            if (App.RunningInBackground)
            {
                return;
            }
            string status = "Status : ";

            switch (args.Status)
            {
                case PositionStatus.Disabled:
                    // the application does not have the right capability or the location master switch is off
                    status += "location is disabled in phone settings";
                    break;

                case PositionStatus.Initializing:
                    // the geolocator started the tracking operation
                    status += "initializing";
                    break;

                case PositionStatus.NoData:
                    // the location service was not able to acquire the location
                    status += "no data";
                    break;

                case PositionStatus.Ready:
                    // the location service is generating geopositions as specified by the tracking parameters
                    status += "ready";
                    break;

                case PositionStatus.NotAvailable:
                    status += "not available";
                    // not used in WindowsPhone, Windows desktop uses this value to signal that there is no hardware capable to acquire location information
                    break;

                case PositionStatus.NotInitialized:
                    // the initial state of the geolocator, once the tracking operation is stopped by the user the geolocator moves back to this state
                    status += "not initialized";
                    break;
            }
            // IMPORTANT: the event handler is called on a worker thread,
            // so we must use the Dispatcher to update the UI from the main thread
            Dispatcher.BeginInvoke(() =>
            {
                this.txtStatus.Text = status;
            });
        }
        protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
        {
            this.StopLocationTracking();
        }

        private void StopLocationTracking()
        {
            if (App.Geolocator != null)
            {
                App.Geolocator.PositionChanged -= geolocator_PositionChanged;
                App.Geolocator.StatusChanged -= geolocator_StatusChanged;
                App.Geolocator = null;
            }
        }
       
        #endregion

        private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            MessageBoxResult Result = MessageBox.Show("Are your want exit application", "Exit Application", MessageBoxButton.OKCancel);

            if (Result == MessageBoxResult.Cancel)

                e.Cancel = true;
            else
            {
                if (NavigationService.CanGoBack)
                {
                    while (NavigationService.RemoveBackEntry() != null)
                    {
                        Global.SaveSettings();

                        NavigationService.RemoveBackEntry();
                    }
                }
            }
        }

        private void PitchSlider_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
        {
            MapControl.Pitch = PitchSlider.Value;
        }
    }
}